package cn.amaake.magicplugin.rpc.service;

import cn.amaake.magicplugin.rpc.config.DubboConfig;
import cn.amaake.magicplugin.rpc.model.RpcInfo;
import cn.amaake.magicplugin.rpc.model.RpcJsonBean;
import cn.amaake.magicplugin.rpc.model.RpcParamData;
import org.apache.dubbo.config.*;
import org.apache.dubbo.rpc.service.GenericException;
import org.apache.dubbo.rpc.service.GenericService;
import org.ssssssss.script.MagicScript;
import org.ssssssss.script.MagicScriptContext;

import javax.script.ScriptEngine;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MagicApiGenericService implements GenericService {

    private String serviceName;
    private List<RpcInfo> rpcInfoList;
    private boolean isEnable;
    private ServiceConfig<GenericService> serviceServiceConfig;
    private boolean isExported = false;

    public MagicApiGenericService(String serviceName,List<RpcInfo> rpcInfoList) {
        this.serviceName = serviceName;
        this.rpcInfoList = rpcInfoList;
        countIsEnable();
    }

    public void countIsEnable() {
        if (rpcInfoList.isEmpty()){
            isEnable = false;
        }
        boolean allDisabled = rpcInfoList.stream().allMatch(rpcInfo -> !rpcInfo.isEnabled());
        if (allDisabled) {
            isEnable = false;
        } else {
            isEnable =  true;
        }
    }


    @Override
    public Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException {
        RpcInfo rpcInfo = rpcInfoList.stream()
                .filter(functionInfo1 -> functionInfo1.getPath().replace("/","").equals(method))
                .findFirst()
                .orElse(null);

        if (rpcInfo == null && !rpcInfo.isEnabled()) {
            return new RpcJsonBean<>(0,"该RPC接口未开放！");
        }
        List<RpcParamData> parameters = rpcInfo.getParamData();
        Map<String, Object> params = new HashMap<>();
        if (parameters != null) {
            if (!parameters.isEmpty()) {
                if(parameters.size() != args.length){
                    return new RpcJsonBean<>(0,"参数位数不一致！");
                }
                // 注入变量信息
                for(int i = 0;i < parameters.size();i++){
                    params.put(parameters.get(i).getFieldName(), args[i]);
                }
            }
        }
        String script = rpcInfo.getScript();
        MagicScript magicScript = MagicScript.create(script, (ScriptEngine)null);
        MagicScriptContext context = new MagicScriptContext(params);
        return new RpcJsonBean<>(magicScript.execute(context));
    }

    public ServiceConfig<GenericService> registerService(DubboConfig dubboConfig,String applicationName){
        serviceServiceConfig = new ServiceConfig<GenericService>();
        ApplicationConfig application = new ApplicationConfig();
        application.setName(applicationName);
        serviceServiceConfig.setApplication(application);
        ProtocolConfig protocolConfig= dubboConfig.getProtocol();
        if(protocolConfig!=null){
            serviceServiceConfig.setProtocol(protocolConfig);
        }
        RegistryConfig registryConfig = dubboConfig.getRegistry();
        if (registryConfig != null) {
            serviceServiceConfig.setRegistry(registryConfig);
        }
        ProviderConfig providerConfig = new ProviderConfig();
        providerConfig.setTimeout(5000);
        serviceServiceConfig.setProvider(providerConfig);
        // 弱类型接口名
        serviceServiceConfig.setInterface(serviceName);
        //serviceServiceConfig.setVersion("1.0.0");
        serviceServiceConfig.setRef((GenericService)this);
        serviceServiceConfig.setGeneric("true");
        if(isEnable){
            serviceServiceConfig.export();
        }

        return serviceServiceConfig;
    }

    public ServiceConfig<GenericService> getServiceServiceConfig() {
        return serviceServiceConfig;
    }

    public void setServiceServiceConfig(ServiceConfig<GenericService> serviceServiceConfig) {
        this.serviceServiceConfig = serviceServiceConfig;
    }

    public List<RpcInfo> getRpcInfoList() {
        return rpcInfoList;
    }

    public void setRpcInfoList(List<RpcInfo> rpcInfoList) {
        this.rpcInfoList = rpcInfoList;
    }

    public boolean isEnable() {
        return isEnable;
    }

    public void setEnable(boolean enable) {
        isEnable = enable;
    }

    public boolean isExported() {
        return isExported;
    }

    public void setExported(boolean exported) {
        isExported = exported;
    }


}
